跳到主要内容

透明窗口在 Windows 上有哪些限制?

考察点​

  • transparent: true 的代价
  • 异形窗口、阴影、点击穿透的实现边界

参考答案​

1. 基本开法​

const win = new BrowserWindow({
transparent: true,
frame: false,
hasShadow: false, // Windows 上透明和系统阴影经常不能同时要
backgroundColor: '#00000000',
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
},
});

页面背景用 background: transparent,圆角和异形由 CSS 画。

2. Windows 上的限制​

  • 系统阴影基本没有。hasShadow: true 会出一口黑底或直接失效。阴影要用 CSS box-shadow,或者窗外再垫一层
  • 不能和部分硬件加速路径共存。老显卡上透明窗口会花、会透出桌面残影。需要准备关闭透明的降级开关
  • 点击行为:透明像素默认仍属于窗口。要做到“透明处点穿到桌面”,用 setIgnoreMouseEvents(true, { forward: true }),再在需要点击的 DOM 区域把鼠标事件打开。forward: true 才能继续收到鼠标移动,用来判断现在是不是在可点击区域上
  • 圆角和最大化:最大化时圆角要去掉,否则四个角透出桌面
  • 截图和录屏:透明区域在部分采集里会变成黑色或白色

macOS 对透明和阴影友好一些,仍要注意全屏、多显示器拖拽时的重绘。

3. 点击穿透示例​

// preload 把渲染进程的命中结果告诉主进程
ipcMain.on('hover:interactive', (event, interactive) => {
const win = BrowserWindow.fromWebContents(event.sender);
// interactive 为 false 时,点击落到窗口后面
win?.setIgnoreMouseEvents(!interactive, { forward: true });
});

渲染进程根据 mousemove 的目标是不是按钮来发这个事件,并且要节流,否则每像素一次 IPC。

4. 什么时候不要用透明窗口​

普通矩形主界面用无边框 + 不透明背景就够了。透明窗口只留给悬浮球、歌词、小组件。它更吃 GPU,也更容易在远程桌面里出问题。

面试话术​

透明窗口是 frame:false 加 transparent。Windows 上系统阴影基本要放弃,改用 CSS。透明像素默认仍会挡住鼠标,点穿要用 setIgnoreMouseEvents,并用 forward 保留 mousemove 来切换可点区域。主界面不要为了圆角去开整窗透明。

常见追问​

  • 圆角一定要透明窗口吗? macOS 可以用隐藏标题栏加系统圆角。Windows 11 有系统圆角能力,但 Electron 里不总是好控,很多团队仍用 CSS。
  • 穿透开了之后窗口收不到点击? 说明切回 ignore: false 的区域判断漏了,或者 IPC 太慢,鼠标已经点下去才切回来。命中检测要在本地做,少依赖往返。